package com.apikey.auth.config;

import com.apikey.auth.interceptor.ApiKeyInterceptor;
import com.apikey.auth.provider.ApiKeyUserProvider;
import com.apikey.auth.service.ApiKeyService;
import com.apikey.auth.service.impl.DefaultApiKeyPermissionValidator;
import com.apikey.auth.service.impl.DefaultApiKeyUserProvider;
import com.apikey.auth.validator.ApiKeyPermissionValidator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * API Key管理框架自动配置类
 * 提供Spring Boot自动配置支持，允许用户通过配置文件启用/禁用功能
 * 支持自定义实现的依赖注入
 *
 * @author API Key Framework
 * @version 1.0
 */
@Configuration
@EnableConfigurationProperties(ApiKeyProperties.class)
@ConditionalOnProperty(prefix = "apikey", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import({ApiKeyJpaConfig.class})
public class ApiKeyAutoConfiguration implements WebMvcConfigurer {

    private final ApiKeyProperties properties;

    /**
     * 构造函数
     *
     * @param properties API Key配置属性
     */
    public ApiKeyAutoConfiguration(ApiKeyProperties properties) {
        this.properties = properties;
    }

    /**
     * 配置默认的用户提供者实现
     * 如果用户没有提供自定义实现，则使用默认实现
     *
     * @return 默认用户提供者实例
     */
    @Bean
    @ConditionalOnMissingBean(ApiKeyUserProvider.class)
    public ApiKeyUserProvider defaultApiKeyUserProvider() {
        return new DefaultApiKeyUserProvider();
    }

    /**
     * 配置默认的权限验证器实现
     * 如果用户没有提供自定义实现，则使用默认实现
     *
     * @return 默认权限验证器实例
     */
    @Bean
    @ConditionalOnMissingBean(ApiKeyPermissionValidator.class)
    public ApiKeyPermissionValidator defaultApiKeyPermissionValidator() {
        return new DefaultApiKeyPermissionValidator();
    }

    /**
     * 配置API Key拦截器
     * 只有在启用拦截器的情况下才会创建
     *
     * @param apiKeyService API Key服务
     * @param userProvider 用户提供者
     * @param permissionValidator 权限验证器
     * @return API Key拦截器实例
     */
    // @Bean
    // @ConditionalOnProperty(prefix = "apikey.interceptor", name = "enabled", havingValue = "true", matchIfMissing = true)
    // public ApiKeyInterceptor apiKeyInterceptor() {
    //     return new ApiKeyInterceptor();
    // }

    /**
     * 注册API Key拦截器到Spring MVC
     * 根据配置的路径模式进行拦截
     *
     * @param registry 拦截器注册表
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 为管理页面的API请求启用拦截器，但排除管理页面本身
        if (properties.getInterceptor().isEnabled()) {
            // 通过Spring容器获取ApiKeyInterceptor实例，确保依赖注入正常工作
            ApiKeyInterceptor interceptor = apiKeyInterceptor();
            registry.addInterceptor(interceptor)
                    .addPathPatterns("/api/**")
                    .excludePathPatterns(
                            "/apikey-admin/**",
                            "/error",
                            "/favicon.ico",
                            "/actuator/**",
                            "/h2-console/**",
                            "/static/**",
                            "/css/**",
                            "/js/**",
                            "/images/**"
                    )
                    .order(properties.getInterceptor().getOrder());
        }
    }

    /**
     * 配置API Key拦截器Bean
     * 确保拦截器的依赖注入正常工作
     *
     * @return API Key拦截器实例
     */
    @Bean
    @ConditionalOnProperty(prefix = "apikey.interceptor", name = "enabled", havingValue = "true", matchIfMissing = true)
    public ApiKeyInterceptor apiKeyInterceptor() {
        return new ApiKeyInterceptor();
    }

    /**
     * 配置Web静态资源
     * 为管理页面提供静态资源访问支持
     */
    @Configuration
    @ConditionalOnProperty(prefix = "apikey.web", name = "enabled", havingValue = "true", matchIfMissing = true)
    public static class ApiKeyWebConfiguration implements WebMvcConfigurer {

        private final ApiKeyProperties properties;

        public ApiKeyWebConfiguration(ApiKeyProperties properties) {
            this.properties = properties;
        }

        /**
         * 添加静态资源处理器
         *
         * @param registry 资源处理器注册表
         */
        @Override
        public void addResourceHandlers(org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry registry) {
            if (properties.getWeb().isEnabled()) {
                String contextPath = properties.getWeb().getContextPath();

                // 注册静态资源处理器
                registry.addResourceHandler(contextPath + "/**")
                        .addResourceLocations("classpath:/static/")
                        .setCachePeriod(properties.getWeb().getCachePeriod())
                        .resourceChain(true);
            }
        }

        /**
         * 添加视图控制器，配置路由映射
         *
         * @param registry 视图控制器注册表
         */
        @Override
        public void addViewControllers(org.springframework.web.servlet.config.annotation.ViewControllerRegistry registry) {
            // 根路径访问用户申请页面
            registry.addViewController("/").setViewName("forward:/index.html");
            
            // /admin 路径访问管理后台
            registry.addViewController("/admin").setViewName("forward:/admin/index.html");
            registry.addViewController("/admin/").setViewName("forward:/admin/index.html");
            
            // 其他 /admin/* 路径也重定向到管理后台入口
            registry.addViewController("/admin/**").setViewName("forward:/admin/index.html");
        }
    }

    /**
     * 配置管理控制器
     * 提供API Key管理的REST接口
     */
    @Configuration
    @ConditionalOnProperty(prefix = "apikey.management", name = "enabled", havingValue = "true", matchIfMissing = true)
    public static class ApiKeyManagementConfiguration {

        /**
         * 配置API Key控制器
         *
         * @return API Key控制器实例
         */
        // @Bean
        // public com.apikey.auth.controller.ApiKeyController apiKeyController() {
        //     return new com.apikey.auth.controller.ApiKeyController();
        // }

        /**
         * 注册访问日志控制器
         *
         * @return 访问日志控制器实例
         */
        // @Bean
        // public com.apikey.auth.controller.AccessLogController accessLogController() {
        //     return new com.apikey.auth.controller.AccessLogController();
        // }

        /**
         * 注册历史记录控制器
         *
         * @return 历史记录控制器实例
         */
        // @Bean
        // public com.apikey.auth.controller.HistoryController historyController() {
        //     return new com.apikey.auth.controller.HistoryController();
        // }
    }

    /**
     * 配置安全相关设置
     * 提供API Key安全策略配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "apikey.security", name = "enabled", havingValue = "true", matchIfMissing = true)
    public static class ApiKeySecurityConfiguration {

        private final ApiKeyProperties properties;

        public ApiKeySecurityConfiguration(ApiKeyProperties properties) {
            this.properties = properties;
        }

        /**
         * 配置API Key安全策略
         *
         * @return 安全策略配置Bean
         */
        @Bean
        public ApiKeySecurityConfig apiKeySecurityConfig() {
            ApiKeySecurityConfig config = new ApiKeySecurityConfig();

            ApiKeyProperties.Security security = properties.getSecurity();
            config.setMaxFailedAttempts(security.getMaxFailedAttempts());
            config.setLockoutDuration(security.getLockoutDuration());
            config.setRateLimitEnabled(security.isRateLimitEnabled());
            config.setMaxRequestsPerMinute(security.getMaxRequestsPerMinute());
            config.setIpWhitelistEnabled(security.isIpWhitelistEnabled());
            config.setAllowedIps(security.getAllowedIps());

            return config;
        }
    }

    /**
     * 配置监控相关设置
     * 提供API Key使用情况监控
     */
    @Configuration
    @ConditionalOnProperty(prefix = "apikey.monitoring", name = "enabled", havingValue = "true", matchIfMissing = false)
    public static class ApiKeyMonitoringConfiguration {

        private final ApiKeyProperties properties;

        public ApiKeyMonitoringConfiguration(ApiKeyProperties properties) {
            this.properties = properties;
        }

        /**
         * 配置监控指标收集器
         *
         * @param apiKeyService API Key服务
         * @return 监控指标收集器实例
         */
        @Bean
        public ApiKeyMetricsCollector apiKeyMetricsCollector(ApiKeyService apiKeyService) {
            return new ApiKeyMetricsCollector(apiKeyService, properties.getMonitoring());
        }

        /**
         * 配置监控端点
         *
         * @param metricsCollector 指标收集器
         * @return 监控端点实例
         */
        @Bean
        public ApiKeyMonitoringEndpoint apiKeyMonitoringEndpoint(ApiKeyMetricsCollector metricsCollector) {
            return new ApiKeyMonitoringEndpoint(metricsCollector);
        }
    }

    /**
     * API Key安全配置类
     * 封装安全相关的配置参数
     */
    public static class ApiKeySecurityConfig {
        private int maxFailedAttempts = 5;
        private long lockoutDuration = 300000; // 5分钟
        private boolean rateLimitEnabled = false;
        private int maxRequestsPerMinute = 60;
        private boolean ipWhitelistEnabled = false;
        private java.util.List<String> allowedIps = new java.util.ArrayList<>();

        // Getters and Setters
        public int getMaxFailedAttempts() {
            return maxFailedAttempts;
        }

        public void setMaxFailedAttempts(int maxFailedAttempts) {
            this.maxFailedAttempts = maxFailedAttempts;
        }

        public long getLockoutDuration() {
            return lockoutDuration;
        }

        public void setLockoutDuration(long lockoutDuration) {
            this.lockoutDuration = lockoutDuration;
        }

        public boolean isRateLimitEnabled() {
            return rateLimitEnabled;
        }

        public void setRateLimitEnabled(boolean rateLimitEnabled) {
            this.rateLimitEnabled = rateLimitEnabled;
        }

        public int getMaxRequestsPerMinute() {
            return maxRequestsPerMinute;
        }

        public void setMaxRequestsPerMinute(int maxRequestsPerMinute) {
            this.maxRequestsPerMinute = maxRequestsPerMinute;
        }

        public boolean isIpWhitelistEnabled() {
            return ipWhitelistEnabled;
        }

        public void setIpWhitelistEnabled(boolean ipWhitelistEnabled) {
            this.ipWhitelistEnabled = ipWhitelistEnabled;
        }

        public java.util.List<String> getAllowedIps() {
            return allowedIps;
        }

        public void setAllowedIps(java.util.List<String> allowedIps) {
            this.allowedIps = allowedIps;
        }
    }

    /**
     * API Key监控指标收集器
     * 收集和统计API Key使用情况
     */
    public static class ApiKeyMetricsCollector {
        private final ApiKeyService apiKeyService;
        private final ApiKeyProperties.Monitoring monitoringConfig;

        public ApiKeyMetricsCollector(ApiKeyService apiKeyService, ApiKeyProperties.Monitoring monitoringConfig) {
            this.apiKeyService = apiKeyService;
            this.monitoringConfig = monitoringConfig;
        }

        /**
         * 收集API Key使用指标
         *
         * @return 指标数据Map
         */
        public java.util.Map<String, Object> collectMetrics() {
            java.util.Map<String, Object> metrics = new java.util.HashMap<>();

            try {
                // 基础统计
                metrics.put("total_api_keys", apiKeyService.getTotalCount());
                metrics.put("active_api_keys", apiKeyService.getActiveCount());

                // 使用情况统计
                java.time.LocalDateTime now = java.time.LocalDateTime.now();
                java.time.LocalDateTime dayAgo = now.minusDays(1);

                // 这里可以添加更多的监控指标
                metrics.put("timestamp", System.currentTimeMillis());

            } catch (Exception e) {
                metrics.put("error", "Failed to collect metrics: " + e.getMessage());
            }

            return metrics;
        }
    }

    /**
     * API Key监控端点
     * 提供监控数据的HTTP端点
     */
    public static class ApiKeyMonitoringEndpoint {
        private final ApiKeyMetricsCollector metricsCollector;

        public ApiKeyMonitoringEndpoint(ApiKeyMetricsCollector metricsCollector) {
            this.metricsCollector = metricsCollector;
        }

        /**
         * 获取监控指标
         *
         * @return 监控指标数据
         */
        public java.util.Map<String, Object> getMetrics() {
            return metricsCollector.collectMetrics();
        }
    }
}